home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / Framewrk / FWPart / Sources / FWDrCmd.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  23.1 KB  |  751 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWDrCmd.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWFrameW.hpp"
  11.  
  12. #ifndef FWDRCMD_H
  13. #include "FWDrCmd.h"
  14. #endif
  15.  
  16. // ----- Framework Includes -----
  17.  
  18. #ifndef FWPART_H
  19. #include "FWPart.h"
  20. #endif
  21.  
  22. #ifndef FWFRAME_H
  23. #include "FWFrame.h"
  24. #endif
  25.  
  26. #ifndef FWSELECT_H
  27. #include "FWSelect.h"
  28. #endif
  29.  
  30. #ifndef FWEVENT_H
  31. #include "FWEvent.h"
  32. #endif
  33.  
  34. #ifndef FWUTIL_H
  35. #include "FWUtil.h"
  36. #endif
  37.  
  38. #ifndef FWPRESEN_H
  39. #include "FWPresen.h"
  40. #endif
  41.  
  42. #ifndef FWLNKMGR_H
  43. #include "FWLnkMgr.h"
  44. #endif
  45.  
  46. // ----- OS Layer -----
  47.  
  48. #ifndef FWODGEOM_H
  49. #include "FWODGeom.h"
  50. #endif
  51.  
  52. #ifndef FWREGION_H
  53. #include "FWRegion.h"
  54. #endif
  55.  
  56. #ifndef FWBARRAY_H
  57. #include "FWBArray.h"
  58. #endif
  59.  
  60. // ----- OpenDoc Includes -----
  61.  
  62. #ifndef SOM_Module_OpenDoc_Commands_defined
  63. #include <CmdDefs.xh>
  64. #endif
  65.  
  66. #ifndef SOM_ODSession_xh
  67. #include <ODSessn.xh>
  68. #endif
  69.  
  70. #ifndef SOM_ODClipboard_xh
  71. #include <Clipbd.xh>
  72. #endif
  73.  
  74. #ifndef SOM_Module_OpenDoc_StdProps_defined
  75. #include <StdProps.xh>
  76. #endif
  77.  
  78. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  79. #include <StdTypes.xh>
  80. #endif
  81.  
  82. #ifndef SOM_ODStorageUnit_xh
  83. #include <StorageU.xh>
  84. #endif
  85.  
  86. #ifndef SOM_ODFacet_xh
  87. #include <Facet.xh>
  88. #endif
  89.  
  90. #ifndef SOM_ODDragAndDrop_xh
  91. #include <DragDrp.xh>
  92. #endif
  93.  
  94. #ifndef SOM_ODDragItemIterator_xh
  95. #include <DgItmIt.xh>
  96. #endif
  97.  
  98. #ifndef _TRANSFORM_
  99. #include <Trnsform.xh>
  100. #endif
  101.  
  102. #ifndef SOM_ODLinkSpec_xh
  103. #include <LinkSpec.xh>
  104. #endif
  105.  
  106. // ----- Macintosh Includes -----
  107.  
  108. #if defined(FW_BUILD_MAC) && !defined(__DRAG__)
  109. #include <Drag.h>
  110. #endif
  111.  
  112. //========================================================================================
  113. //    Runtime Info
  114. //========================================================================================
  115.  
  116. #if FW_LIB_EXPORT_PRAGMAS
  117. #pragma lib_export on
  118. #endif
  119.  
  120. #ifdef FW_BUILD_MAC
  121. #pragma segment FWFrameworkCommands
  122. #endif
  123.  
  124. FW_DEFINE_CLASS_M1(FW_CDragCommand, FW_CCommand)
  125. FW_DEFINE_CLASS_M1(FW_CDropCommand, FW_CCommand)
  126.  
  127. //========================================================================================
  128. //    constants
  129. //========================================================================================
  130.  
  131. //static const ODPropertyName    FW_kPropFrameInfo = "Apple:ODF:Property:FrameInfo";
  132.  
  133. //========================================================================================
  134. // FW_CDragCommand class
  135. //========================================================================================
  136.  
  137. //----------------------------------------------------------------------------------------
  138. // FW_CDragCommand constructor
  139. //----------------------------------------------------------------------------------------
  140.  
  141. FW_CDragCommand::FW_CDragCommand(Environment* ev,
  142.                                  FW_CFrame* frame, 
  143.                                  FW_Boolean canUndo) :
  144.     FW_CCommand(ev, FW_kDragCommand, frame, canUndo),
  145.     fDragRegion(),
  146.     fDestPart(NULL)
  147. {
  148.     fBeganTransaction = FALSE;
  149.     fDragResult = kODDropFail;
  150.  
  151.     if (canUndo)
  152.     {
  153.         fActionType = kODEndAction;
  154.         // Set menu strings here so that we don't pass NULL strings to OpenDoc when AddAction is called
  155.         this->SetMenuStrings(ev, "Undo Drag-Move", "Redo Drag-Move");
  156.     }
  157.  
  158.     FW_END_CONSTRUCTOR
  159. }
  160.  
  161. //----------------------------------------------------------------------------------------
  162. // FW_CDragCommand destructor
  163. //----------------------------------------------------------------------------------------
  164.  
  165. FW_CDragCommand::~FW_CDragCommand()
  166. {
  167. }
  168.  
  169. //----------------------------------------------------------------------------------------
  170. // FW_CDragCommand::DoIt
  171. //----------------------------------------------------------------------------------------
  172.  
  173. void FW_CDragCommand::DoIt(Environment* ev)    // Override
  174. {
  175.     this->DragCompleted(ev);
  176.  
  177.     if (fCanUndo)
  178.         this->SaveRedoState(ev);
  179. }
  180.  
  181. //----------------------------------------------------------------------------------------
  182. // FW_CDragCommand::CommitDone
  183. //----------------------------------------------------------------------------------------
  184.  
  185. void FW_CDragCommand::CommitDone(Environment* ev)
  186. {
  187.     if (fCanUndo)
  188.         if (this->HasAddedAction(ev) && this->IsDragMoveToAnotherPart(ev))
  189.             this->FreeUndoState(ev);
  190. }
  191.  
  192. //----------------------------------------------------------------------------------------
  193. // FW_CDragCommand::BeginDrag
  194. //----------------------------------------------------------------------------------------
  195.  
  196. void FW_CDragCommand::BeginDrag(Environment* ev, const FW_CMouseEvent& theMouseEvent)
  197. {
  198.     ODPart* destPart;
  199.     ODID frameID;
  200.     ODDragAndDrop*    drag;
  201.     ODStorageUnit*    dragSU;
  202.  
  203.     ODFacet* facet = theMouseEvent.GetFacet(ev);
  204.     
  205.     // ----- In the following block we focus on the window -----
  206.     {
  207.         FW_CWindowContext wc(ev, facet);
  208.     
  209.         FW_CRect selectionBounds;    // selectionBounds is in content coordinate
  210.  
  211.         // ----- Scope for aqDragShape and aqWindowContentTransform -----
  212.         {
  213.             FW_CAcquiredODShape    aqDragShape(this->CreateDragShape(ev, facet));
  214.             selectionBounds = FW_GetShapeBoundingBox(ev, aqDragShape);
  215.  
  216.             FW_CAcquiredODTransform aqWindowContentTransform = facet->AcquireWindowContentTransform(ev, NULL);
  217.             aqDragShape->Transform(ev, aqWindowContentTransform);
  218.  
  219.             fDragRegion = ::FW_CopyRegion(::FW_GetShapeRegion(ev, aqDragShape));
  220.         }
  221.         
  222. #ifdef FW_BUILD_MAC
  223.         // ----- fDragRegion must be in screen coordinate on the Mac
  224.         Point localToGlobal = {FW_QDGlobals.thePort->portRect.top, FW_QDGlobals.thePort->portRect.left};
  225.         ::LocalToGlobal(&localToGlobal);
  226.         FW_CPoint offset(localToGlobal);
  227.         ::FW_OffsetRegion(fDragRegion, offset.x, offset.y);
  228. #endif        
  229.  
  230.         //  ----- Fill Drag and Drop SU with Props n' Vals
  231.         drag = fPart->GetSession(ev)->GetDragAndDrop(ev);
  232.         drag->Clear(ev);
  233.         dragSU = drag->GetContentStorageUnit(ev);
  234.         
  235.         // ----- write out the contents of the drag
  236.         fSelection->ExternalizeData(ev, fFrame, FW_kDragAndDropStorage, dragSU, kODCloneCut);
  237.         
  238. /*    
  239.         [HLX] I am not sure why I have to do that?
  240.         // ----- save ID of frame being dragged
  241.         frameID = fFrame->GetID(ev);
  242.         dragSU->AddProperty(ev, FW_kPropFrameInfo)->AddValue(ev, kODULong);
  243.  
  244.         FW_CByteArray byteArray(&frameID, sizeof(ODID));
  245.         dragSU->SetValue(ev, byteArray);
  246. */
  247.         // ----- save offset between mousedown pt and topLeft pt of selection
  248.         // (must convert to Content coordinates first)
  249.         FW_CPoint mouseOffset = theMouseEvent.GetMousePosition(ev, FW_CMouseEvent::kFrame);
  250.         FW_CFrame* frame = FW_CFrame::ODtoFWFrame(ev, facet->GetFrame(ev));
  251.         frame->GetContentView(ev)->FrameToViewContent(ev, mouseOffset);
  252.         
  253.         mouseOffset -= selectionBounds.TopLeft();
  254.         
  255.         dragSU->AddProperty(ev, kODPropMouseDownOffset)->AddValue(ev, kODPoint);
  256.  
  257.         FW_CByteArray byteArray(&mouseOffset, sizeof(FW_CPoint));
  258.         dragSU->SetValue(ev, byteArray);
  259.  
  260.         // ----- Write out Link Spec if possible -----
  261.         if (theMouseEvent.IsItemModifier(ev) && !fPart->IsReadOnly(ev))    // command key is down
  262.         {
  263.             FW_CLinkManager* linkMgr = fPart->GetLinkManager(ev);
  264.             if (linkMgr && fSelection->IsSelectionPublishable(ev))
  265.             {
  266.                 ODLinkSpec* linkSpec = NULL;
  267.                 FW_VOLATILE(linkSpec);
  268.                 ODUpdateID updateID = fPart->GetSession(ev)->UniqueUpdateID(ev); // need data to put in the link spec
  269.                 FW_CByteArray data(&updateID, sizeof(updateID));
  270.         
  271.                 FW_TRY
  272.                 {
  273.                     linkSpec = fPart->GetStorageUnit(ev)->GetDraft(ev)->CreateLinkSpec(ev, fPart->GetODPart(ev), data);
  274.                     dragSU->AddProperty(ev, kODPropLinkSpec);
  275.                     linkSpec->WriteLinkSpec(ev, dragSU);
  276.                 }
  277.                 FW_CATCH_BEGIN
  278.                 FW_CATCH_EVERYTHING()
  279.                 {
  280.                     // exception occurred - just continue without the link spec
  281.                     if (linkSpec)
  282.                     {
  283.                         delete linkSpec;
  284.                         linkSpec = NULL;
  285.                     }
  286.                     // FW_THROW_SAME();
  287.                 }
  288.                 FW_CATCH_END
  289.         
  290.                 if (linkSpec)
  291.                 {
  292.                     // Create a publisher
  293.                     FW_CPublishLink* publishLink = linkMgr->NewPublishLink(ev, updateID, fFrame->GetPresentation(ev));
  294.                     linkMgr->SetPendingDropLink(ev, publishLink);
  295.                     delete linkSpec;
  296.                 }
  297.             }
  298.         }
  299.  
  300.         fPart->Dragging(ev, fFrame, TRUE);
  301.         if (fCanUndo)                        // post an empty Begin action
  302.         {
  303.             ODUndo* undo = fPart->GetSession(ev)->GetUndo(ev);
  304.             undo->MarkActionHistory(ev);    // in case operation fails and we need to roll back transactions
  305.             this->AddAction(ev, kODBeginAction, NULL, 0, fUndoString, fRedoString);
  306.             fBeganTransaction = TRUE;
  307.         }
  308.  
  309.         FW_CMouseEvent dragEvent(ev, theMouseEvent);
  310.         ODEventData* eventData = dragEvent.GetPlatformEvent();
  311.         FW_CByteArray dragRegionBArray(&fDragRegion, sizeof(fDragRegion));        
  312.         FW_CByteArray dragEventBArray(&eventData, sizeof(ODEventData*));
  313.  
  314.         fDragResult = drag->StartDrag(ev, fFrame->GetODFrame(ev), kODDragImageRegionHandle, dragRegionBArray, &destPart, dragEventBArray);
  315.  
  316.         fDestPart = destPart;
  317.         if (!this->IsDragMoveToAnotherPart(ev))    // can only Undo drag-move to another part
  318.             fCanUndo = FALSE;
  319.     }
  320. }
  321.  
  322. //----------------------------------------------------------------------------------------
  323. // FW_CDragCommand::IsDragMoveToAnotherPart
  324. //----------------------------------------------------------------------------------------
  325. FW_Boolean FW_CDragCommand::IsDragMoveToAnotherPart(Environment* ev)
  326. {
  327.     return (fDragResult == kODDropMove && fDestPart != fPart->GetODPart(ev));
  328. }
  329.  
  330. //----------------------------------------------------------------------------------------
  331. // FW_CDragCommand::DragCompleted
  332. //----------------------------------------------------------------------------------------
  333.  
  334. void FW_CDragCommand::DragCompleted(Environment* ev)
  335. {
  336.     if (this->IsDragMoveToAnotherPart(ev))    // it's a move to another part
  337.     {
  338.         if (fCanUndo)
  339.             this->SaveUndoState(ev);
  340.  
  341.         if (!fSelection->ClearSelection(ev))
  342.             fDragResult = kODDropFail;
  343.     }
  344.     
  345.     if (fDestPart)
  346.     {
  347.         fDestPart->Release(ev);
  348.         fDestPart = NULL;
  349.     }
  350.     
  351.     fPart->Dragging(ev, fFrame, FALSE);
  352.  
  353.     ::FW_DisposeRegion(fDragRegion);
  354.     
  355.     this->AdjustUndo(ev);
  356. }
  357.  
  358. //----------------------------------------------------------------------------------------
  359. // FW_CDragCommand::CreateDragShape
  360. //----------------------------------------------------------------------------------------
  361.  
  362. ODShape* FW_CDragCommand::CreateDragShape(Environment* ev, ODFacet* facet)
  363. {
  364.     return fSelection->CreateSelectionOutline(ev, facet, fFrame);
  365. }
  366.  
  367. //----------------------------------------------------------------------------------------
  368. // FW_CDragCommand::AdjustUndo
  369. //----------------------------------------------------------------------------------------
  370.  
  371. void FW_CDragCommand::AdjustUndo(Environment* ev)
  372. {
  373.     // Check for failure, and if so clean up
  374.     if (fDragResult == kODDropFail)                // Drag&Drop operation failed somewhere along the line
  375.     {
  376.         fCausesChange = FALSE;                    // Don't call part->Changed()
  377.         if (fCanUndo)                            // cancel the Undo!
  378.         {
  379.             this->FreeUndoState(ev);            // Discard any data saved for Undo
  380.             fCanUndo = FALSE;
  381.         }
  382.  
  383.         if (fBeganTransaction)                    // we've already added a Begin action
  384.         {
  385.             this->AbortTransaction(ev);            // clear unfinished transactions from Undo stack
  386.             fBeganTransaction = FALSE;
  387.         }
  388.     }
  389.     else if (fBeganTransaction && !fCanUndo)    // fCanUndo was turned off after BeginAction was added
  390.     {
  391.         // add an EndAction to finish the transaction, since PerformCommand won't
  392.         this->AddAction(ev, kODEndAction, NULL, 0, fUndoString, fRedoString);
  393.         fBeganTransaction = FALSE;
  394.     }
  395. }
  396.  
  397. //----------------------------------------------------------------------------------------
  398. // FW_CDragCommand::AbortTransaction
  399. //----------------------------------------------------------------------------------------
  400.  
  401. void FW_CDragCommand::AbortTransaction(Environment* ev)
  402. {
  403.     // First add a bogus End action so the Undo object doesn't think it's in the middle of a transaction
  404.     this->AddAction(ev, kODEndAction, NULL, 0, fUndoString, fRedoString);
  405.  
  406.     // Now clear the Undo stack back to our mark, which is just before the Begin action
  407.     ODUndo* undo = fPart->GetSession(ev)->GetUndo(ev);
  408.     undo->ClearActionHistory(ev, kODRespectMarks);
  409. }
  410.  
  411. //========================================================================================
  412. // FW_CDropCommand
  413. //========================================================================================
  414.  
  415. //----------------------------------------------------------------------------------------
  416. // FW_CDropCommand constructor
  417. //----------------------------------------------------------------------------------------
  418.  
  419. FW_CDropCommand::FW_CDropCommand(Environment* ev,
  420.                                  FW_CPart* itsPart, 
  421.                                  FW_CFrame* frame, 
  422.                                  ODDragItemIterator* dropInfo, 
  423.                                  ODFacet* facet, 
  424.                                  const FW_CPoint& dropPoint,
  425.                                  FW_Boolean canUndo) :
  426.     FW_CCommand(ev, FW_kDropCommand, frame , canUndo),
  427.     fDropItemIterator(dropInfo),
  428.     fFacet(facet),
  429.     fDropPoint(dropPoint)
  430. {
  431.     fDroppedInSameFrame = FALSE;
  432.     fDropResult = kODDropFail;
  433. }
  434.  
  435. //----------------------------------------------------------------------------------------
  436. // FW_CDropCommand destructor
  437. //----------------------------------------------------------------------------------------
  438.  
  439. FW_CDropCommand::~FW_CDropCommand()
  440. {
  441. }
  442.  
  443. //----------------------------------------------------------------------------------------
  444. // FW_CDropCommand::DoIt
  445. //----------------------------------------------------------------------------------------
  446.  
  447. FW_DECLARE_THROW_POINT(FW_CDropCommand_DoIt_BeforeHandleDrop);
  448. FW_DECLARE_THROW_POINT(FW_CDropCommand_DoIt_AfterHandleDrop);
  449.  
  450. void FW_CDropCommand::DoIt(Environment* ev)    // Override
  451. {
  452.     if (!fFrame->GetCanAcceptDrop(ev))
  453.         fDropResult = kODDropFail;
  454.     else
  455.     {
  456.         if (fCanUndo)
  457.             this->SaveUndoState(ev);
  458.         FW_TRY {
  459.             FW_CHECK_THROW_POINT (FW_CDropCommand_DoIt_BeforeHandleDrop);
  460.             fDropResult = this->HandleDrop(ev);
  461.         }
  462.         FW_CATCH_BEGIN
  463.         FW_CATCH_EVERYTHING () {
  464.             if (fCanUndo)
  465.                 FreeUndoState (ev);
  466.             FW_THROW_SAME ();
  467.         }
  468.         FW_CATCH_END
  469.     }
  470.     FW_CHECK_THROW_POINT (FW_CDropCommand_DoIt_AfterHandleDrop);
  471.     this->AdjustUndo(ev); // won't fail
  472.     
  473.     // Now that we've successfully dropped, "protect" it by supressing any subsequent
  474.     // failures. We *don't* rethrow now because undo is less important.
  475.     
  476.     if (fCanUndo) {
  477.         FW_TRY {
  478.             this->SaveRedoState(ev);
  479.         }
  480.         FW_CATCH_BEGIN
  481.         FW_CATCH_EVERYTHING () {
  482.             // Having already called HandleDrop and performed the major work of this
  483.             // command we *really* want to avoid passing exceptions up. It would be nice
  484.             // if we could put up an alert saying that Redo won't be supported, though.
  485.         }
  486.         FW_CATCH_END
  487.     }
  488. }
  489.  
  490. //----------------------------------------------------------------------------------------
  491. // FW_CDropCommand::AdjustUndo
  492. //----------------------------------------------------------------------------------------
  493.  
  494. void FW_CDropCommand::AdjustUndo(Environment* ev)
  495. {
  496.     if (fDropResult == kODDropFail)        // Drop failed--can't Undo
  497.     {
  498.         if (fCanUndo)
  499.             this->FreeUndoState(ev);            // Discard any data saved for Undo
  500.         fCanUndo = FALSE;                        // Don't call AddActionToHistory
  501.         fCausesChange = FALSE;                    // Don't call fPart->Changed()
  502.     }
  503. }
  504.  
  505. //----------------------------------------------------------------------------------------
  506. // FW_CDropCommand::CommitUndone
  507. //----------------------------------------------------------------------------------------
  508.  
  509. void FW_CDropCommand::CommitUndone(Environment* ev)
  510. {
  511.     if (fCanUndo)
  512.         if (!this->IsDragMoveInSameFrame(ev))
  513.             this->FreeRedoState(ev);
  514. }
  515.  
  516. //----------------------------------------------------------------------------------------
  517. // FW_CDropCommand::DoDrop
  518. //----------------------------------------------------------------------------------------
  519.  
  520. FW_Boolean FW_CDropCommand::DoDrop(    Environment* ev,
  521.                                     ODStorageUnit* dropSU,
  522.                                     const FW_CPoint& mouseOffset, 
  523.                                     const FW_CPoint& dropPoint,
  524.                                     FW_Boolean isDropMove)
  525. {
  526.     FW_UNUSED(mouseOffset);
  527.     FW_UNUSED(dropPoint);
  528.     
  529.     ODCloneKind cloneKind = (isDropMove ? kODCloneDropMove : kODCloneDropCopy);
  530.  
  531.     FW_Boolean result = FALSE;
  532.     FW_TRY
  533.     {
  534.         result = fSelection->InternalizeData(ev, fFrame, dropSU, cloneKind) != FW_kInternalizeFailed;
  535.     }
  536.     FW_CATCH_BEGIN
  537.     FW_CATCH_EVERYTHING()
  538.     {
  539.         FW_THROW_SAME();
  540.     }
  541.     FW_CATCH_END
  542.         
  543.     return result;
  544. }
  545.  
  546. //----------------------------------------------------------------------------------------
  547. // FW_CDropCommand::DoDroppedInSameFrame
  548. //----------------------------------------------------------------------------------------
  549.  
  550. FW_Boolean FW_CDropCommand::DoDroppedInSameFrame(Environment* ev,
  551.                                                  ODStorageUnit* dropSU,
  552.                                                  const FW_CPoint& originPoint, 
  553.                                                  const FW_CPoint& dropPoint)
  554. {
  555.     FW_UNUSED(dropSU);
  556.     FW_UNUSED(originPoint);
  557.     FW_UNUSED(dropPoint);
  558.     
  559.     return FALSE;
  560. }
  561.  
  562. //----------------------------------------------------------------------------------------
  563. // FW_CDropCommand::GetDropOrigin
  564. //----------------------------------------------------------------------------------------
  565.  
  566. void FW_CDropCommand::GetDropOrigin(Environment* ev, FW_CPoint& originPoint)
  567. {
  568.     // ----- Calculate originPoint (in content coordinate)
  569.     FW_SPlatformPoint dragOrigin;
  570.     
  571.     ODDragAndDrop* drag = fPart->GetSession(ev)->GetDragAndDrop(ev);
  572.     
  573. #ifdef FW_BUILD_MAC
  574.     DragReference theDrag = drag->GetDragReference(ev);
  575.     ::GetDragOrigin(theDrag, &dragOrigin);
  576.     ::GlobalToLocal(&dragOrigin);
  577. #endif
  578. #ifdef FW_BUILD_WIN
  579.     dragOrigin = drag->GetDragOrigin(ev);
  580.     FW_CAcquiredODWindow aqODWindow = fFacet->AcquireWindow(ev);
  581.     ::ScreenToClient(aqODWindow->GetPlatformWindow(ev), &dragOrigin);
  582. #endif
  583.  
  584.     originPoint = dragOrigin;
  585.         
  586.     FW_CAcquiredODTransform aqWindowContentTransform = fFacet->AcquireWindowContentTransform(ev, NULL);
  587.     originPoint.InverseTransform(ev, aqWindowContentTransform);
  588. }
  589.  
  590. //----------------------------------------------------------------------------------------
  591. // FW_CDropCommand::HandleDrop
  592. //----------------------------------------------------------------------------------------
  593.  
  594. FW_DECLARE_THROW_POINT (FW_CDropCommand_HandleDrop_AfterFirstDrop);
  595.  
  596. ODDropResult FW_CDropCommand::HandleDrop(Environment* ev)
  597. {
  598.     ODStorageUnit *dropSU;
  599.     FW_CPoint originPoint, dropPoint;
  600.     ODDropResult dropResult = kODDropFail;        // assume the worst
  601.     FW_Boolean acceptedDrop = FALSE;
  602.     FW_Boolean handledDrop = FALSE;
  603.  
  604.     ODDragAndDrop* drag = fPart->GetSession(ev)->GetDragAndDrop(ev);
  605.     
  606.     this->GetDropOrigin(ev, originPoint);
  607.     unsigned long attributes = drag->GetDragAttributes(ev);
  608.     FW_Boolean isDropMove = (attributes & kODDropIsMove);
  609.     
  610.     if ((attributes & kODDropIsPasteAs) && fFrame->GetWindow(ev)->IsActive(ev))    // check that the window is in the foreground
  611.     {
  612.         FW_Boolean createdLink = FALSE;
  613.         dropSU = fDropItemIterator->First(ev);
  614.         acceptedDrop = this->HandlePasteAsDialog(ev, dropSU, handledDrop, createdLink);
  615.         if (handledDrop && acceptedDrop)
  616.         {
  617.             fCommandID = kODCommandPasteAs;
  618.             this->DoDroppedPasteAs(ev, originPoint, fDropPoint);
  619.         }
  620.         if (createdLink)    // If the drop created a link, return kODDropCopy regardless of the drop attributes.
  621.             return kODDropCopy;
  622.     }
  623.     
  624.     if (!handledDrop)
  625.     {
  626.     /*    Regarding exception handling...
  627.         What happens if we are dropping several items and the first goes Ok but a later
  628.         one causes an exception to be thrown? Should be try to undo the previous drops
  629.         or just exit (not having fully cleaned up)? We are not going to clean up, on
  630.         the theory that you probably want dropped objects to stick around. If whoever
  631.         called us assumes that we are going to either completely succeed or completely
  632.         fail (i.e. not exit with a partial state change) then there may be a problem.
  633.         This situation comes up every time we have a loop with a state change in it.
  634.     */
  635.         // ----- Iterate thru dropped items
  636.         for (dropSU = fDropItemIterator->First(ev); dropSU && !acceptedDrop;
  637.                 dropSU = fDropItemIterator->Next(ev))
  638.         {        
  639.             if ((attributes & kODDragIsInSourceFrame) && isDropMove)
  640.             {
  641.                 acceptedDrop = this->DoDroppedInSameFrame(ev, dropSU, originPoint, fDropPoint);
  642.                 fPart->DeletePromise(ev, FW_kDragAndDropStorage);
  643.                 fDroppedInSameFrame = TRUE;
  644.             }
  645.             else
  646.             {
  647.                 FW_CPoint mouseDownOffset;
  648.                 if (dropSU->Exists(ev, kODPropMouseDownOffset, kODPoint, 0))
  649.                 {
  650.                     dropSU->Focus(ev, kODPropMouseDownOffset, kODPosUndefined, kODPoint, 0, kODPosFirstSib);
  651.                     FW_CByteArray byteArray;
  652.                     dropSU->GetValue(ev, sizeof(FW_CPoint), byteArray);
  653.                     byteArray.CopyBuffer(&mouseDownOffset, sizeof(FW_CPoint));
  654.                 }
  655.  
  656.                 ODWindow* window = fFacet->GetWindow(ev);
  657.                 if (!window->IsActive(ev))
  658.                     window->Select(ev);
  659.                     
  660.                 ODFrame* odFrame = fFacet->GetFrame(ev);
  661.                 FW_CFrame* frame = FW_CFrame::ODtoFWFrame(ev, odFrame);
  662.                 frame->ActivateFrame(ev, fFacet);
  663.                 
  664.                 acceptedDrop = this->DoDrop(ev, dropSU, mouseDownOffset, fDropPoint, isDropMove);
  665.             }
  666.             FW_CHECK_THROW_POINT (FW_CDropCommand_HandleDrop_AfterFirstDrop);
  667.         }
  668.     }
  669.  
  670.     // ----- Return drop result
  671.     if (acceptedDrop)
  672.         dropResult = (isDropMove ? kODDropMove : kODDropCopy);
  673.         
  674.     return dropResult;
  675. }
  676.  
  677. //----------------------------------------------------------------------------------------
  678. // FW_CDropCommand::HandlePasteAsDialog
  679. //----------------------------------------------------------------------------------------
  680. FW_Boolean FW_CDropCommand::HandlePasteAsDialog(Environment* ev, ODStorageUnit* dropSU,
  681.                                                 FW_Boolean& handledDrop, FW_Boolean& createdLink)
  682. {
  683.     FW_Boolean result = FALSE;
  684.     ODPasteAsMergeSetting mergeSetting;
  685.     ODBoolean canPasteLink = FALSE;
  686.     FW_CLinkManager* linkMgr = fPart->GetLinkManager(ev);
  687.     ODPasteAsResult pasteAsResult;
  688.  
  689.     // ---- Check whether the selection supports linking ----
  690.     if (linkMgr && fSelection->CanSubscribe(ev, mergeSetting))
  691.     {
  692. /*        if (dropSU->Exists(ev, kODPropLinkSpec, (ODValueType)NULL, 0)) [MEB] OpenDoc does this */
  693.             canPasteLink = TRUE;
  694.     }
  695.  
  696.     // ---- Display the Paste As... dialog ----
  697.     ODDragAndDrop* drag = fPart->GetSession(ev)->GetDragAndDrop(ev);
  698.     result = drag->ShowPasteAsDialog(ev, canPasteLink, mergeSetting, 
  699.                                      fFrame->GetActiveFacet(ev),    // facet from which dialog is triggered
  700.                                      fFrame->GetViewType(ev),        // viewType of data
  701.                                      dropSU, &pasteAsResult);
  702.  
  703.     if (result == kODFalse)
  704.         handledDrop = TRUE;            // we tried, but the user cancelled
  705.     else
  706.     {
  707.         // --- Figure out what to do depending on settings from Paste As dialog
  708.         if (pasteAsResult.pasteLinkSetting == kODTrue)        // user wants to create a Link
  709.         {
  710.             result = linkMgr->PasteWithLink(ev, dropSU, pasteAsResult, fFrame->GetPresentation(ev));
  711.             if (result)
  712.                 createdLink = TRUE;    // let the caller know that a link was created
  713.             handledDrop = TRUE;
  714.         }
  715.         else if (pasteAsResult.mergeSetting == kODFalse)    // user wants to embed a Part w/o Linking
  716.         {
  717.             result = this->DoPasteAsEmbed(ev, dropSU);
  718.             handledDrop = TRUE;
  719.         }
  720.         else     // Merge with Contents - let Drag&Drop command handle this
  721.             handledDrop = FALSE;
  722.     }
  723.  
  724.     return result;
  725. }
  726.  
  727. //----------------------------------------------------------------------------------------
  728. // FW_CDropCommand::DoDroppedPasteAs
  729. //----------------------------------------------------------------------------------------
  730. void FW_CDropCommand::DoDroppedPasteAs(Environment* ev, 
  731.                                        const FW_CPoint& originPoint, 
  732.                                        const FW_CPoint& dropPoint)
  733. {
  734.     FW_UNUSED(originPoint);
  735.     FW_UNUSED(dropPoint);
  736.  
  737.     // Override to perform post-Drop positioning on the items that were dropped
  738. }
  739.  
  740. //----------------------------------------------------------------------------------------
  741. // FW_CDropCommand::DoPasteAsEmbed
  742. //----------------------------------------------------------------------------------------
  743. FW_Boolean FW_CDropCommand::DoPasteAsEmbed(Environment* ev, ODStorageUnit* storageUnit)
  744. {
  745.     FW_UNUSED(storageUnit);
  746.  
  747.     // Override to paste the contents of the storageUnit as an embedded part (no linking)
  748.     return FALSE;
  749. }
  750.  
  751.